#include "configmanager.h"
#include "qtconcurrentrun.h"
#include "identtracker.h"
#include "preprocessor.h"
#include "cvalgedgedetection.h"

IdentTracker::IdentTracker(float scaleFactor):scaleFactor_(scaleFactor),isInit(false)
{
    //scaleFactor_ = ConfigManager::getInstance().getParameter("preprocessing","scaleFactor").toFloat();
    similarity_ = 0;
}

IdentTracker::~IdentTracker()
{
    
}

void IdentTracker::initTemplate(const cv::Mat &templateImg,const cv::Rect &roi)
{
    tracker = nullptr;

    ident_roi = roi;
    LogDebug << "templateImg Identifi src" << templateImg.cols << "|" << templateImg.rows;

    cv::Mat grayFrame;
    if (templateImg.channels() == 3)
    {
        cv::cvtColor(templateImg, grayFrame, cv::COLOR_RGB2GRAY);
    }
    ident_Img = grayFrame.clone();
    LogDebug << "ident_Img Identifi src" << ident_Img.cols << "|" << ident_Img.rows;
    cv::Mat scaledtemplateImg;
    cv::Rect scaledidentRoi;
    scaleImage(grayFrame, scaledtemplateImg, scaleFactor_);
    scaledidentRoi.width = ident_roi.width * scaleFactor_;
    scaledidentRoi.height = ident_roi.height * scaleFactor_;
    LogDebug << "ident_Img scaledtemplateImg src" << scaledtemplateImg.cols << "|" << scaledtemplateImg.rows;
    initialize(scaledtemplateImg,roi);
    LogDebug << "initTemplate Template Identifi is  saved";
    isInit = true;
}



void IdentTracker::initialize(const cv::Mat &templateImg, const cv::Rect &roi)
{

}

cv::Rect2d IdentTracker::detectAndMatch(const cv::Mat &frame,float &Similarity)
{

}

void IdentTracker::initializeKCF(const cv::Mat& frame, const cv::Rect2d& roi)
{
    tracker = cv::TrackerKCF::create();
    tracker->init(frame, roi);
    LogDebug << "KCF tracker initialized with ROI: " << roi;
}

void IdentTracker::setScaleFactor(double scaleFactor)
{
    std::lock_guard<std::mutex> lock(mutex);
    scaleFactor_ = scaleFactor;
    if(!ident_Img.empty())
    {
        cv::Mat scaledtemplateImg;
        cv::Rect scaledidentRoi;

        scaleImage(ident_Img, scaledtemplateImg, scaleFactor_);
        scaledidentRoi.width = ident_roi.width * scaleFactor;
        scaledidentRoi.height = ident_roi.height * scaleFactor;
        initialize(scaledtemplateImg,scaledidentRoi);
        LogDebug << "Scale factor successfull ";
    }
    LogDebug << "Scale factor set to: " << scaleFactor_ << "restart initTemplate";
}

cv::Rect2d IdentTracker::scaleRect(const cv::Rect2d& rect, double scale) const
{
    return cv::Rect2d(rect.x * scale, rect.y * scale, rect.width * scale, rect.height * scale);
}

void IdentTracker::scaleImage(const cv::Mat& src, cv::Mat& dst, double scale) const
{
    if(scale == 1)
    {
        dst = src;
        return;
    }
    cv::resize(src, dst, cv::Size(), scale, scale);
}

bool IdentTracker::trackv2(const cv::Mat& frame, cv::Rect2d& roi)
{
    double topdiff,bottomdiff;
    cv::Vec4f topFitLine, bottomFitLine;
    std::vector<cv::Point> defects, topPoints, bottomPoints;
    int maxDeviation = ParamValue.getParameter<int>("cvInspection","boundaryThreshold");
    CvAlgEdgeDetection::detectEdgeDefects(frame, maxDeviation, defects,
                                          topPoints, bottomPoints, topFitLine,
                                          bottomFitLine,topdiff,bottomdiff);



}

bool IdentTracker::track(const cv::Mat& frame, cv::Rect2d& roi)
{
    enablePreTracking = PreProcessor::getInstance().enablePreTracking();
    std::lock_guard<std::mutex> lock(mutex);
    cv::Mat scaledFrame;
    LogTrack << "Starting track. Frame size: " << frame.cols << "x" << frame.rows;
    scaleImage(frame, scaledFrame, scaleFactor_);
    scaleRect(roi,scaleFactor_);
    LogTrack << "track src: " << roi;
    // qDebug() << "scaleFactor_:" << scaleFactor_;
    // qDebug() << "Target: " << (roi.x + roi.width / 2) * scaleFactor_;
    if (scaledFrame.empty()) {
        LogError << "Scaled frame is empty after scaling.";
        return false;

    }
    LogTrack << "Starting scaledFrame. Frame size: " << scaledFrame.cols << "x" << scaledFrame.rows;
    if (enablePreTracking && tracker!=nullptr)
    {
        try
        {
            if (tracker->update(scaledFrame, roi))
            {
                LogDebug << "KCF tracking  with ROI: " << roi;
                roi = scaleRect(roi, 1.0 / scaleFactor_);
                //initializeKCF(scaledFrame, roi);
                return true;
            }
        }
        catch (const cv::Exception& e)
        {
            LogError << "Exception during tracker update: " << e.what();
        }

    }

    //LogWarning << "KCF tracking failure, switching to detect and match";
    cv::Rect2d roiTemp = detectAndMatch(scaledFrame , similarity_);
    if(roiTemp.empty())
    {
        return false;
    }
    roi = roiTemp;
    LogTrack << "track to: " << roi;
    if (enablePreTracking && roi.width > 0 && roi.height > 0) {
        initializeKCF(scaledFrame, roi);
    }
    roi = scaleRect(roi, 1.0 / scaleFactor_);
    return true;
}

void IdentTracker::setEnablePreTracking(bool enablePreTracking_)
{
    enablePreTracking  = enablePreTracking_;
}

void IdentTracker::setcaleFactor(float scaleFactor_)
{
    scaleFactor = scaleFactor_ ;
    LogDebug << "go in Slot exposureDataChange";
    QtConcurrent::run([this,scaleFactor_]() {
        this->setScaleFactor(scaleFactor_);
    });
}
